Amazon GuardDuty が EKS ランタイムモニタリングをサポートしたため手動でセットアップしてみた
こんにちは!AWS事業本部コンサルティング部のたかくに(@takakuni_)です。
Amazon GuardDuty が Amazon EKS のコンテナランタイムを監視するようになりました。
今回提供されたランタイムモニタリング機能では DaemonSet 形式で GuardDuty エージェントをデプロイし、ファイルアクセス、プロセス実行、ネットワーク接続など、ホスト上のオペレーティング システム レベルの動作を監視します。
GuardDuty エージェントの管理方法には、自動管理
と手動管理
の2種類があり、今回はセットアップ編と題して、後者の手動管理を主に解説できればと思います。
前提条件
執筆時点(2023/4/8 時点)では今回の Amazon GuardDuty ランタイムモニタリングには、いくつか制約事項があるためピックアップします。
- EKS on EC2 のみサポート
- ECS on EC2, ECS on Fargate, EKS on Fargate は未サポート
- CPU アーキテクチャは AMD のみサポート
- ARM アーキテクチャは未サポート
- OS は Amazon Linux 2 のみ動作検証済み
- Bottlerocket OS を含む、その他 OS は未検証
最新情報は 公式ドキュメント - EKS Runtime Monitoring をご覧ください。
カバレッジ機能の提供
GuardDuty では新しくカバレッジ機能を提供しました。
カバレッジでは EKS ランタイムモニタリングが行えるかどうかのステータスを表す画面です。
ランタイムモニタリングを行なっているクラスターの割合を表示したり、ランタイムモニタリングが行えない場合のトラブルシューティングとしても役立つ画面になっています。
EKS ランタイムモニタリングを利用するには
手動管理の場合、 EKS ランタイムモニタリングを利用するには、以下のステップを踏む必要があります。
- Amazon GuardDuty コンソールからランタイムモニタリング機能の有効化を行う
- VPC Endpoint を配置して EKS クラスターがサービスエンドポイントに到達できるようにする
- EKS add-ons を有効化し EKS クラスターに GuardDuty エージェントをデプロイする
ランタイムモニタリングの有効化
GuardDuty コンソールから「EKS Protection」をクリックし、「EKS ランタイムモニタリング」を有効化します。
設定の編集画面に遷移すると、今回新たに追加された「EKS ランタイムモニタリング」と「エージェントを自動的に管理する」が設定できます。
今回は手動管理のため、以下で設定します。
- EKS ランタイムモニタリング:有効
- エージェントを自動的に管理する:無効
VPC Endpoint を配置
EKS クラスターがサービスエンドポイントに到達するためには VPC Endpoint (com.amazonaws.${region}.guardduty-data
) が必要です。
NAT Gateway や 直接パブリック IP でサービスエンドポイントには到達できません。
The Amazon EKS worker node instances can run in non-public subnets. The GuardDuty agent running on these nodes can't reach the public endpoint for GuardDuty without using an Amazon VPC endpoint.
Understanding why GuardDuty chose Amazon VPC endpoint
ちなみにですが、 VPC Endpoint を作らず NAT Gateway 越しに GuardDuty エージェントがサービスエンドポイントを解決しようとすると、以下のようなエラーになります。
takakuni@~ % kubectl logs aws-guardduty-agent-bxq2r -n amazon-guardduty
2023-04-08T13:26:28.465770Z INFO amzn_guardduty_agent: GuardDuty agent starting with 8 worker thread(s) and 100 max blocking threads.
2023-04-08T13:26:28.569217Z INFO amzn_guardduty_agent: Agent fingerprint: f3962a7b731cfd20ce9570140f7d481102c18ca98465439ddb299a047f6ef95e
2023-04-08T13:26:28.583339Z ERROR amzn_guardduty_agent::dependency_checks: Failed to ping agent endpoint due to reqwest::Error {
kind: Request,
url: Url {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"guardduty-data.ap-northeast-1.amazonaws.com",
),
),
port: None,
path: "/ping",
query: None,
fragment: None,
},
source: hyper::Error(
Connect,
ConnectError(
"dns error",
Os {
code: 16,
kind: ResourceBusy,
message: "Device or resource busy",
},
),
),
}
2023-04-08T13:26:28.583367Z ERROR amzn_guardduty_agent: Dependency check failed - Failed to communicate with back-end services, please check your network configuration
Error: Pipeline(DependencyError("Failed to communicate with back-end services, please check your network configuration"))
セキュリティグループの設定
VPC Endpoint で作成するセキュリティグループでは、 HTTPS(443 番ポート)で EKS クラスターを実行している VPC の CIDR を許可する必要があります。
表にすると以下のようになります。
インバウンドルール
タイプ | プロトコル | ポート範囲 | CIDR |
---|---|---|---|
HTTPS | TCP | 443 | EKS クラスターを実行している VPC の CIDR |
アウトバウンドルール
無しで OK
vpce.tf
resource "aws_security_group" "vpce" {
name = "${local.prefix}-sg-vpce"
description = "${local.prefix}-sg-vpce"
vpc_id = module.vpc.vpc_id
ingress {
description = "HTTPS from VPC CIDR"
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = [
module.vpc.vpc_cidr_block
]
}
tags = {
Name = "${local.prefix}-sg-vpce"
}
}
resource "aws_vpc_endpoint" "guardduty_data" {
vpc_id = module.vpc.vpc_id
vpc_endpoint_type = "Interface"
service_name = "com.amazonaws.${data.aws_region.current.name}.guardduty-data"
policy = templatefile("${path.module}/iam_policy_document/vpc_endpoint_gd_data.json", {
account_id = data.aws_caller_identity.self.account_id
})
security_group_ids = [aws_security_group.vpce.id]
private_dns_enabled = true
subnet_ids = module.vpc.private_subnets
tags = {
Name = "${local.prefix}-vpce-guardduty-data"
}
}
VPC エンドポイントポリシー
上記のように VPC Endpoint のセキュリティグループは、 ポート 443 を 0.0.0.0/0
で許可する必要があります。そのため、セキュリティをより強固に保つには、 VPC エンドポイントポリシーを利用して、より細かな制御を行う必要があります。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "*",
"Resource": "*",
"Effect": "Allow",
"Principal": "*"
},
{
"Condition": {
"StringNotEquals": {
"aws:PrincipalAccount": "111122223333"
}
},
"Action": "*",
"Resource": "*",
"Effect": "Deny",
"Principal": "*"
}
]
}
料金
幸いなことに、 EKS Runtime Monitoring が有効かつ、 EKS クラスター上で GuardDuty エージェントを実行している場合(EKS add-onsが有効な場合)、 ランタイムモニタリングのために設置した VPC Endpoint (com.amazonaws.${region}.guardduty-data
) は無料で利用できます。
As long as you have enabled EKS Runtime Monitoring and have a GuardDuty agent running on your EKS clusters, you won't get charged for the network costs to send the secure telemetry (Runtime event types) to GuardDuty.
Understanding why GuardDuty chose Amazon VPC endpoint
EKS add-ons の有効化
今回のランタイムモニタリング機能は EKS の add-ons (aws-guardduty-agent
) 機能を利用します。
コンソールまたは、AWS CLI, IaC から EKS の add-ons を有効化します。
コンソールからは、「Amazon GuardDuty EKS Runtime Monitoring
」と表示されていますが、実際の識別子は aws-guardduty-agent
です。
EKS add-ons を有効化すると、 DaemonSet 形式で GuardDuty エージェント (Pod) が配置されていきます。
【抜粋】 eks.tf
resource "aws_eks_addon" "aws_guardduty_agent" {
cluster_name = aws_eks_cluster.cluster.name
addon_name = "aws-guardduty-agent"
addon_version = "v1.0.0-eksbuild.1"
resolve_conflicts = "OVERWRITE"
}
カバレッジの確認
上記の手順が完了すると、 EKS クラスターがランタイムモニタリングを監視できる状態になります。
カバレッジで該当する EKS クラスターが Healty
になっていることを確認します。
まとめ
以上、「Amazon GuardDuty が EKS ランタイムモニタリングをサポートしたため手動でセットアップしてみた」でした。
VPC, EKS クラスター 作成から GuardDuty エージェントのセットアップまでを含めたサンプルコードを以下のレポジトリに載せています。(※ 随時更新します)
takakuni-classmethod/gd-rumtime-protection
ぜひ、カバレッジを有効活用いただき、EKS ランタイムモニタリングをご活用ください。
以上、AWS事業本部コンサルティング部のたかくに(@takakuni_)でした!